PostgreSQL 全文搜索 查询解析函数

1 背景知识

PostgreSQL提供了以下函数,将一个查询转换成 tsquery 数据类型。

to_tsquery
plainto_tsquery
phraseto_tsquery
websearch_to_tsquery

1.1 to_tsquery

to_tsquery 提供了比 plainto_tsqueryphraseto_tsquery 更多的特性,但是它对其输入要求更加严格。

1.2 websearch_to_tsquery

websearch_to_tsqueryto_tsquery 的一个简化版本,类似于Web搜索引擎使用的语法。

2 to_tsquery

to_tsquery 函数从 querytext 创建一个 tsquery 值。querytext 由操作符 &(AND)、|(OR)、!(NOT)、<->(FOLLOWED BY)和单词 组成。

2.1 语法定义

to_tsquery([ config regconfig, ] querytext text) returns tsquery

对于 tsqueryto_tsquery 把每一个 记号 正规化成一个 词位,并且丢弃掉任何是停用词的 记号。一个具体的例子如下:

SELECT to_tsquery('english', 'The & Fat & Rats');
  to_tsquery   
---------------
 'fat' & 'rat'
(1 row)

2.2 权重标签

每一个词位可以添加tsquery 权重,用于限制匹配权重一致的 tsvector 词位。例如:Rats 需要再标题出现,也需要在正文中出现。

SELECT to_tsquery('Doors:AB  & Woman:A');
      to_tsquery       
-----------------------
 'door':AB & 'woman':A
(1 row)

例子

SELECT film_id,title,description 
FROM film 
WHERE fulltext @@ to_tsquery('DOOR:AB & Woman:A');

2.3 匹配标签 *

SELECT to_tsquery('english','Doors:* & Woman:*');
      to_tsquery      
----------------------
 'door':* & 'woman':*
(1 row)

例子

SELECT film_id,title,description 
FROM film 
WHERE fulltext @@ to_tsquery('DOOR:* & Woman:*');
-[ RECORD 1 ]---------------------------
film_id     | 584
title       | MIXED DOORS
description | A Taut Drama of a Womanizer And a Lumberjack who must Succumb a Pioneer in Ancient India
-[ RECORD 2 ]-----------------------------
film_id     | 243
title       | DOORS PRESIDENT
description | A Awe-Inspiring Display of a Squirrel And a Woman who must Overcome a Boy in The Gulf of Mexico

2.4 短语句标签

to_tsquery 函数也能够传入段语句。根据标准词典supernovae 正规化为 supernova,也将 stars 正规化为 star

SELECT to_tsquery('''supernovae stars'' & !crab');
            to_tsquery            
----------------------------------
 'supernova' <-> 'star' & !'crab'
(1 row)

3 plainto_tsquery

3.1 语法定义

plainto_tsquery([ config regconfig, ] querytext text) returns tsquery

3.2 未格式化的文本

将未格式化的文本 querytext 转换成一个 tsquery 值。然后插入 &(AND)布尔操作符词词位之间。

SELECT plainto_tsquery('english', 'The Fat Rats');
//屏幕输出:
 plainto_tsquery 
-----------------
 'fat' & 'rat'
(1 row)

3.3 忽略其他的符号

Warning

注意: plainto_tsquery 不会识别 tsquery 操作符、权重标签匹配标签

这里,所有的的符号将被丢弃。

SELECT plainto_tsquery('english', 'The Fat & Rats:C');
//屏幕输出:
   plainto_tsquery   
---------------------
 'fat' & 'rat' & 'c'

3.4 plainto_tsquery 与 to_tsquery 区别

to_tsquery 传入 '''xxxxx''' 字符串形式。而 plainto_tsquery 只需要传入 'xxx' 字符串形式。

testdb=# SELECT to_tsquery('english', '''The Fat Rats''');
//屏幕输出:
   to_tsquery    
-----------------
 'fat' <-> 'rat'
(1 row)

4 phraseto_tsquery

phraseto_tsqueryplainto_tsquery 相似。但是还是有细微差别。

  1. phraseto_tsquery 会插入 <->(FOLLOWED BY) 操作符,而 plainto_tsquery 会插入 & (AND) 操作符。
  2. 停用词通过插入 <N> 操作符,而不是 <-> 操作符。在搜索准确的词位位置时这个函数很有用,因为 FOLLOWED BY 操作符不只是检查所有词位的存在性,还会检查词位的顺序。

4.1 语法定义

phraseto_tsquery([ config regconfig, ] querytext text) returns tsquery

4.2 未格式化的文本

SELECT phraseto_tsquery('english', 'The Fat Rats');
//屏幕输出:
 phraseto_tsquery
------------------
 'fat' <-> 'rat'

4.3 忽略其他的符号

plainto_tsquery 相似,phraseto_tsquery 会丢弃 tsquery 操作符、权重标签匹配标签

SELECT phraseto_tsquery('english', 'The Fat & Rats:C');
//屏幕输出:
      phraseto_tsquery
-----------------------------
 'fat' <-> 'rat' <-> 'c'

5 websearch_to_tsquery

websearch_to_tsquery 可以从未格式化文本 querytext 创建一个 tsquery 值。和 plainto_tsquery 以及 phraseto_tsquery 函数不同,它可以识别特定的操作符。此外,这个函数不会报出语法错误,这就可以把原始的用户提供的输入用于搜索。

5.1 语法定义

websearch_to_tsquery([ config regconfig, ] querytext text) returns tsquery

支持下列语法:

5.2 无引号文本

文本将将转换成由 & 操作符分隔的词位,类似 plainto_tsquery 函数。

SELECT websearch_to_tsquery('english', 'The fat rats');
//屏幕输出:
 websearch_to_tsquery
----------------------
 'fat' & 'rat'
(1 row)

5.3 引号文本

文本将被转换成由 <-> 操作符分隔的词,就像被类似 phraseto_tsquery 函数。

SELECT websearch_to_tsquery('english', '"supernovae stars" -crab');
//屏幕输出:
       websearch_to_tsquery
----------------------------------
 'supernova' <-> 'star' & !'crab'
(1 row)

5.4 OR

如果文本中包含“or”,将转换为 | 运算符。

       websearch_to_tsquery
-----------------------------------
 'sad' <-> 'cat' | 'fat' <-> 'rat'
(1 row)

5.5 破折号(-)

破折号将转换为 ! 运算符。

SELECT websearch_to_tsquery('english', 'signal -"segmentation fault"');
         websearch_to_tsquery
---------------------------------------
 'signal' & !( 'segment' <-> 'fault' )
(1 row)

5.6 忽略其他的符号

SELECT websearch_to_tsquery('english', '""" )( dummy \\ query <->');
//屏幕输出:
 websearch_to_tsquery
----------------------
 'dummi' & 'queri'
(1 row)